﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: CompiledQuery.cs
//
//  Description: A query compiled for a given storage.
// 
//--------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Data;
using Chili.Opf3.Storages;

namespace Chili.Opf3.Query
{
	/// <summary>This class represents a storage dependent query.</summary>
	/// <remarks>
	/// 	<para>This query is storage dependent. It is created from any other query type and
	///     can only be executed on the storage it has been compiled for. If you create a
	///     CompiledQuery for MsSql Server (for example) you can execute the query only on a
	///     MsSql Server storage.</para>
	/// 	<para>A CompiledQuery is generated by invoking the
	///     <see cref="Opf3.Query.IQuery.ToCompiledQuery">ToCompiledQuery</see> routine of a
	///     class that implements the <see cref="Opf3.Query.IQuery">IQuery</see> interface.</para>
	/// </remarks>
	/// <example>
	///     The following example shows how to use the <see cref="Opf3.Query.OPath">OPath</see> and
	///     <see cref="Opf3.Query.ObjectExpression">ObjectExpression</see> class to create a CompiledQuery
	///     from a <see cref="Opf3.Query.ObjectQuery{T}">ObjectQuery</see> .
	///     <code lang="CS">
	/// // ... Other code
	///  
	/// // Create an ObjectQuery for User persistent objects and
	/// // add a condition to load only user with a name that contains "hri"
	/// ObjectQuery&lt;User&gt; objectQuery = 
	/// new ObjectQuery&lt;User&gt;("UserName like {0}", "%hri%");
	///  
	/// // Create an ObjectExpression by parsing the ObjectQuery.
	/// ObjectExpression objectExpresion = OPath.Parse(objectQuery);
	///  
	/// // Compile the ObjectExpression to get a CompildQuery.
	/// // You have to set the storage that is used to compile the query.
	/// CompiledQuery compiled = objectExpression.ToCompiledQuery(ObjectContext.Storage);
	///  
	/// // ... Other code
	///     </code>
	/// </example>
	[Serializable]
	public sealed class CompiledQuery : IQuery
	{
		private IDbCommand _command;
		private QueryTypes _queryType = QueryTypes.Unknown;
		private AutoNumberItems _autonumberItems;
		private int _timeout;

		/// <summary>
		/// <para>
		/// Creates a new instance of the <see cref="CompiledQuery">CompiledQuery
		/// Class</see>.
		/// </para>
		/// <para>
		/// <b>Attention:</b> Don't create a CompiledQuery in your application. This constructor
		/// is only required for some storage classes. Use <see cref="IQuery.ToCompiledQuery">ToCompiledQuery</see>
		/// instead.
		/// </para>
		/// </summary>
		/// <param name="command">Storage dependent command that is executed on the storage.</param>
		/// <param name="queryType">The <see cref="Opf3.Query.QueryTypes">QueryType</see> of the 
		/// <see cref="CompiledQuery">CompiledQuery</see>.</param>
		/// <exception cref="ArgumentNullException">Command is null.</exception>
		public CompiledQuery(IDbCommand command, QueryTypes queryType)
		{
			if (command == null)
				throw new ArgumentNullException("command");

			_command = command;
			_queryType = queryType;
		}

		/// <summary>
		/// Returns the storage specific command associated with the
		/// <see cref="CompiledQuery">CompiledQuery</see>.
		/// </summary>
		/// <value>A storage dependent command object.</value>
		public IDbCommand Command
		{
			get { return _command; }
		}

		/// <summary>
		/// Specifies the autonumber collection that contains the properties and 
		/// <see cref="Opf3.FieldAttribute">FieldAttributes</see> of the persistent object that is represented
		/// by this query.
		/// </summary>
		public AutoNumberItems AutoNumberItems
		{
			get { return _autonumberItems; }
			set { _autonumberItems = value; }
		}

		/// <summary>
		/// Gets a string representation of the class.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return _command.CommandText;
		}

		#region IQuery Members

		/// <summary>
		/// Converts the <see cref="IQuery">IQuery</see> to an
		/// <see cref="Opf3.Query.CompiledQuery">CompiledQuery</see> that is then executed on a
		/// specific <see cref="Opf3.Storages.IStorage">storage</see>.
		/// </summary>
		/// <returns>
		/// This method is only implemented by the
		/// <see cref="CompiledQuery">CompiledQuery</see> class since the class implements the
		/// <see cref="IQuery">IQuery</see> interface. The method returns the query itself.
		/// </returns>
		/// <param name="storage">
		/// Class that implements the <see cref="Opf3.Storages.IStorage">IStorage</see>
		/// interface. The query is executed on that storage.
		/// </param>
		public CompiledQuery ToCompiledQuery(IStorage storage)
		{
			return this;
		}

		/// <summary>
		/// Specifies the wait time before terminating the attempt to execute a command and generating an error.
		/// </summary>
		/// <value>An integer that specifies the wait time in seconds.</value>
		/// <exception cref="ArgumentException">Value is lower then zero.</exception>
		public int Timeout
		{
			get { return _timeout; }
			set 
			{
				if (value < 0)
					throw new ArgumentException("Value is lower then zero.");
				_timeout = value; 
			}
		}

		/// <summary>
		/// Returns the <see cref="Opf3.Query.QueryTypes">QueryType</see> of the CompiledQuery.
		/// </summary>
		/// <value>
		/// A member of the <see cref="Opf3.Query.QueryTypes">QueryType</see>
		/// enumeration.
		/// </value>
		public QueryTypes QueryType
		{
			get { return _queryType; }
		}

		#endregion
	}
}
